using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using UnityEngine;

namespace JEngine.Framework
{
    public class HttpServer
    {
       
        private HttpListener httpListener;
        private readonly Dictionary<ushort, List<IMHandler>> Handlers = new Dictionary<ushort, List<IMHandler>>();
        private SQLiteHelper sqlite;
        private const string DBNAMEKEY = "Data";
        private const string UIDKEY = "UID";
        private const string USERIDKEY = "UserID";
        private const string JSONKEY = "JsonData";
        private Func<string, object> _deserializerFunc;
        public bool Create(int port, string url)
        {
            try
            {
                InittHttpServer(url, port);
                InitSqDB();
                InitMessageHandler();
                this.LogColor("Server started. Listening for incoming requests...");
                return true;
            }
            catch (Exception e)
            {
                Debug.Log($"Failed to start server: {e.Message}");
                return false;
            }
        }
        public void RegisterDeserializer<T>(Func<string, T> deserializer)
        {
            _deserializerFunc = (json) => deserializer(json);
        }
        //不管有没有就插入一个新的
        public void SaveData_InsertIntoSpecific<T>(T t, int UID) where T : InterTest
        {
            try
            {
                var json = LitJson.JsonMapper.ToJson(t);
                string tableName = typeof(T).FullName;
                sqlite.Getdb((db) =>
                {
                    if (!db.Find(tableName))
                    {
                        db.CreateTable(tableName, new[] {UIDKEY, USERIDKEY, JSONKEY},
                            new[] {"INTEGER PRIMARY KEY", "INTEGER", "TEXT"});
                    }

                    //2插入
                    db.InsertIntoSpecific(tableName, new[] {UIDKEY, USERIDKEY, JSONKEY},
                        new[] {UID.ToString(), t.userID.ToString(), json});
                });
            }
            catch (Exception e)
            {
                Debug.LogError($"SaveData_InsertIntoSpecific Error:{e}");
            }
        }

        //不管有没有就插入一个新的
        public async UniTask<int> SaveData_InsertIntoSpecific<T>(T t) where T : InterTest
        {
            int newUID = -1; // 初始化为-1，表示未找到有效的 UID
            var task = UniTask.Create();
            try
            {
                var json = LitJson.JsonMapper.ToJson(t);
                string tableName = typeof(T).FullName;
                sqlite.Getdb((db) =>
                {
                    if (!db.Find(tableName))
                        CreateTable(db, tableName);

                    // 插入数据
                    db.InsertIntoSpecific(tableName, new[] {USERIDKEY, JSONKEY}, new[] {t.userID.ToString(), json});

                    // 获取最后插入的自增主键值
                    string query = "SELECT last_insert_rowid()";
                    using (var result = db.ExecuteQuery(query))
                    {
                        if (result.HasRows && result.Read())
                        {
                            newUID = result.GetInt32(0); // 获取返回的新的 UID
                        }
                    }

                    task.TrySetResult();
                });
            }
            catch (Exception e)
            {
                Debug.LogError($"SaveData_InsertIntoSpecific Error:{e}");
                task.TrySetResult();
            }

            await task.Task;
            return newUID; // 返回新的 UID
        }

//更新玩家的一条数据
        public async UniTask<bool> UpDateData_UserID<T>(T t) where T : InterTest
        {
            try
            {
                var task = UniTask.Create();
                int count = 0;
                string tableName = typeof(T).FullName;
                sqlite.Getdb((db) =>
                {
                    if (!db.Find(tableName))
                        return;
                    string json = LitJson.JsonMapper.ToJson(t);
                    count = db.UpdateIntoSpecific(tableName, UIDKEY, "=", t.userID.ToString(), JSONKEY, json);
                    task.TrySetResult();
                });
                await task.Task;
                return count != 0;
            }
            catch (Exception e)
            {
                Debug.LogError($"UpDateData_UserID Error:{e}");
                return false;
            }
        }

//更新uid的一个数据
        public async UniTask<bool> UpDateData_UID<T>(T t, int uid) where T : InterTest
        {
            try
            {
                string tableName = typeof(T).FullName;
                int count = 0;
                var task = UniTask.Create();
                sqlite.Getdb((db) =>
                {
                    if (!db.Find(tableName))
                        return;
                    string json = LitJson.JsonMapper.ToJson(t);
                    count = db.UpdateIntoSpecific(tableName, UIDKEY, "=", uid.ToString(), JSONKEY, json);
                    task.TrySetResult();
                });
                await task.Task;
                return count != 0;
            }
            catch (Exception e)
            {
                Debug.LogError($"UpDateData_UID Error: {e}");
                return false;
            }
        }

//删除ui的数据
        public void DeleteData<T>(int uid) where T : InterTest
        {
            string tableName = typeof(T).FullName;
            sqlite.Getdb((db) =>
            {
                if (!db.Find(tableName))
                    return;
                db.Delete(tableName, UIDKEY, "=", uid.ToString());
            });
        }

//读取整个表数据
        public async UniTask<Dictionary<int, T>> Read_Table<T>() where T : InterTest
        {
            try
            {
                string tableName = typeof(T).FullName;
                Dictionary<int, T> dic = new Dictionary<int, T>();
                var task = UniTask.Create();
                sqlite.Getdb((db) =>
                {
                    if (db.Find(tableName))
                    {
                        using (var reader = db.ReadFullTable(tableName))
                        {
                            while (reader.Read())
                            {
                               
                                int uid = reader.GetInt32(reader.GetOrdinal(UIDKEY));
                                string json = reader.GetString(reader.GetOrdinal(JSONKEY));
                                T t = (T)_deserializerFunc(json);
                                dic.Add(uid, t);
                            }
                        }

                        task.TrySetResult();
                    }
                    else
                    {
                        task.TrySetResult();
                    }
                });
                await task.Task;
                return dic;
            }
            catch (Exception e)
            {
                Debug.LogError($"Read_Table Error:{e}");
                return null;
            }
        }


//得到某个uid数据
        public async UniTask<T> Read_UID<T>(int uid) where T : InterTest
        {
            try
            {
                string tableName = typeof(T).FullName;
                T t = default;
                var task = UniTask.Create();
                sqlite.Getdb((db) =>
                {
                    if (db.Find(tableName))
                    {
                        using (var reader = db.Select(tableName, UIDKEY, "=", uid.ToString()))
                        {
                             t = LitJson.JsonMapper.ToObject<T>(reader[JSONKEY].ToString());
                           
                            // Dictionary<string, object> pairs = SQLiteTools.GetValue(reader);
                            // if (pairs != null)
                            //     t = LitJson.JsonMapper.ToObject<T>(pairs[JSONKEY].ToString());
                            task.TrySetResult();
                        }
                    }
                    else
                    {
                        task.TrySetResult();
                    }
                });
                await task.Task;
                return t;
            }
            catch (Exception e)
            {
                Debug.LogError($"根据UID查询失败：{e}");
                return default;
            }
        }


//读取某个玩家的全部数据
        public async UniTask<Dictionary<int, T>> Read_UserID<T>(int userID) where T : InterTest
        {
            try
            {
                string tableName = typeof(T).FullName;
                Dictionary<int, T> dic = new Dictionary<int, T>();
                var task = UniTask.Create();
                sqlite.Getdb((db) =>
                {
                    if (db.Find(tableName))
                    {
                        using (var reader = db.Select(tableName, USERIDKEY, "=", userID.ToString()))
                        {
                            while (reader.Read())
                            {
                                int uid = reader.GetInt32(reader.GetOrdinal(UIDKEY));
                                string json = reader.GetString(reader.GetOrdinal(JSONKEY));
                                T t =  (T)_deserializerFunc(json);
                                dic.Add(uid, t);
                            }

                            task.TrySetResult();
                        }
                    }
                    else
                    {
                        task.TrySetResult();
                    }
                });
                await task.Task;
                return dic;
            }
            catch (Exception e)
            {
                Debug.LogError($"根据USerID查询失败：{e}");
                return null;
            }
        }

        #region API

        private static void CreateTable(DbAccess db, string tableName, int UID = 1001)
        {
            //1创建
            db.CreateTable(tableName, new[] {UIDKEY, USERIDKEY, JSONKEY},
                new[] {"INTEGER PRIMARY KEY AUTOINCREMENT", "INTEGER", "TEXT"});
            db.UpdateIntoSpecific(tableName, UIDKEY, "=", "1", UIDKEY, UID.ToString());
        }

        private void InitMessageHandler()
        {
            var handler = Engine.GetAttribute<HttpMessageHandlerAttribute>();
            foreach (var type in handler)
            {
                IMHandler iMHandler = Activator.CreateInstance(type) as IMHandler;
                if (iMHandler == null)
                {
                    Debug.LogError($"message handle {type.Name} 需要继承 IMHandler");
                    continue;
                }

                Type messageType = iMHandler.GetMessageType();
                ushort opcode = Engine.GetTypeID(messageType);
                if (opcode == 0)
                {
                    Debug.LogError($"消息opcode为0: {messageType.Name}");
                    continue;
                }

                RegisterHandler(opcode, iMHandler);
            }
        }

        private void InitSqDB()
        {
            sqlite = new SQLiteHelper(DBNAMEKEY);
        }

        private void InittHttpServer(string url, int port)
        {
            StringBuilder writeText = new StringBuilder();

            if (!url.StartsWith("http"))
                writeText.Append("http://");
            writeText.Append(url);
            writeText.Append(":");
            writeText.Append(port);
            writeText.Append("/");
            httpListener = new HttpListener();
            httpListener.Prefixes.Add(writeText.ToString());
            httpListener.Start();
            //开始异步接收请求
            httpListener.BeginGetContext(GetContextCallback, null);
        }

        private void RegisterHandler(ushort opcode, IMHandler iMHandler)
        {
            if (!Handlers.ContainsKey(opcode))
            {
                Handlers.Add(opcode, new List<IMHandler>());
            }

            Handlers[opcode].Add(iMHandler);
        }

        private void GetContextCallback(IAsyncResult result)
        {
            if (httpListener == null || !httpListener.IsListening)
                return;

            try
            {
                // 接收到请求并处理
                HttpListenerContext context = httpListener.EndGetContext(result);
                // 继续异步接收下一个请求
                httpListener.BeginGetContext(GetContextCallback, null);
                // 处理请求的逻辑   //新的线程中处理
                ThreadPool.QueueUserWorkItem(HandleRequest, context);
            }
            catch (Exception e)
            {
                Debug.LogError($"Error handling request: {e.Message}");
            }
        }

        private void HandleRequest(object state)
        {
            try
            {
                HttpListenerContext context = (HttpListenerContext) state;
                switch (context.Request.HttpMethod.ToUpper())
                {
                    case "GET":
                        // 处理GET请求
                        break;
                    case "POST":
                        // 处理POST请求
                        string requestBody = new StreamReader(context.Request.InputStream).ReadToEnd();
                        var msg = LitJson.JsonMapper.ToObject(requestBody, typeof(InterTest));
                        InterTest it = msg as InterTest;
                        if (Handlers.ContainsKey(it.opcode))
                        {
                            Debug.Log($"This is a POST request with body: {Handlers[it.opcode][0].GetMessageType().FullName}");

                            foreach (var im in Handlers[it.opcode])
                            {
                                im.Handle(requestBody, context);
                            }
                        }
                        else
                        {
                            context.Response.Close();
                            Debug.LogError($"消息没处理:{Handlers[it.opcode][0].GetMessageType().FullName}");
                        }

                        break;
                    default:
                        // 不支持的方法类型
                        context.Response.StatusCode = (int) HttpStatusCode.MethodNotAllowed;
                        context.Response.Close();
                        return;
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"消息处理错误：{e}");
                throw;
            }
           
        }

        #endregion

       
    }
}